/** **************************************************************************************************************
 * COMPONO Core
 ************************************************************************************************************** **/
function compono(){};
compono.name = "COMPONO";
compono.toString=function(){return this.name+" ["+this.version+"]"};
compono.version={
	toString:function(){return this.major+"."+this.minor+"."+this.add+"."+this.bug+"."+this.release},
	major:1,minor:9,add:0,bug:0,release:0
};


Object.extend = function(source, destination){
	var prop;
	for(prop in source){
		destination[prop]=source[prop]
	};
	return destination;
};
Object.extendForBatchProcessing = function(source, destination, overwrites, customHandler){
	var prop, overwrites = overwrites || false, handler = customHandler || arguments.callee.defaultHandler;
	
	if(destination){
		destination.batchProcessingHandler = handler;
		for(prop in source)
		{
			if( typeof(source[prop])=="function" && ( overwrites == true || (prop in destination) == false))
			{
				destination[prop] = function(){
					return this.batchProcessingHandler(arguments.callee.$function, arguments);
				};
				destination[prop].$function = source[prop];
			}
		};
		return destination;
	}
	
};

//Default function to execute on each collection item
Object.extendForBatchProcessing.defaultHandler = function(handler, args){
	var result = [];
	if(this.length <= 0){
		return this;
	};
	for(var i=0, length = this.length; i < length; i++){
		result.push( handler.apply( this[i], args) )
	};
	return result;
};

/** **************************************************************************************************************
 * DOMContentLoaded
 * http://dean.edwards.name/weblog/2006/06/again/
 ************************************************************************************************************** **/
compono.ready = function($function,$scope){
	var scope = ($scope||arguments.callee.scope||arguments.callee.globalScope||window);
    if(!arguments.callee.loaded){
	   arguments.callee.list[arguments.callee.list.length]={func:$function,scope:scope};
	}else{
	    $function.call(scope);
		arguments.callee.scope = null;
	}
};
compono.ready.list = [];
compono.ready.scope = null;
compono.ready.globalScope = null;

compono.ready.init = function(){
	if(compono.ready.timer){
		clearInterval(compono.ready.timer);
		compono.ready.timer = null;
	};
	var listener;
	while( listener = compono.ready.list.pop() )
	{
		listener.func.call(listener.scope)
	};
	compono.ready.loaded = true;
};


if(document.addEventListener){	/* for Mozilla/Opera9 */
	document.addEventListener("DOMContentLoaded", compono.ready.init, false);
}else if(window.attachEvent&&!window.opera){	/* for Internet Explorer */
	document.write("<script id='__ie_onload' defer src='javascript:void(0)'><\/script>");
	document.getElementById("__ie_onload").onreadystatechange=function(){if(this.readyState=="complete")compono.ready.init();}
}else if(/WebKit/i.test(navigator.userAgent)){ /* for Safari */
	compono.ready.timer = window.setInterval(function(){if(/loaded|complete/.test(document.readyState))compono.ready.init();},10);
}else{
    window.onload = compono.ready.init; /* for other browsers */
}


compono.Class = function(proto){
var k = proto.hasOwnProperty("constructor") ? proto.constructor : function(){};
	k.name = proto.name||"COMPONO [Class]";
	k.Class = arguments.callee;
	k.toString = function(){return this.name;};
	//k.prototype = Object.extend(this.prototype,proto);
	
	k.prototype = proto;
	for(var i in this.prototype){
		if(!k.prototype.hasOwnProperty(i)){
			k.prototype[i] = this.prototype[i];
		}
	};
	
	k.prototype.base = this;
	k.prototype.constructor = k;
	k.prototype.core = compono;
	k.prototype.toString = k.prototype.toString || function(){return this.constructor.name;};
	if(proto.hasOwnProperty("initialize")&&typeof(proto.initialize)=="function"){
		proto.initialize.call(k,proto)
	};
	return k
};

compono.Static = function(proto){
	var k = proto||{};
		k.Static = arguments.callee;
		k.Class = this.Class;
		k.parent = this;
		return Object.extend(this,proto)
};

compono.ui = {};


compono.hash = {
	css:{
		names:{
			get:function(c){
				if(!this.hasOwnProperty(c)){
					this[c] = new RegExp("(?:^|\\s+)"+c+"(?:\\s+|$)","i")
				};
				return this[c]
			}
		},
		property:{
			get:function(c){
				if(!this.hasOwnProperty(c)){
					this[c] = c.replace(/\-(\w)/, function(p,s){
						return s.toUpperCase();
					});
				};
				return this[c]
			}
		}
	},
	selector:{
		get:function(v){
			if(!this.hasOwnProperty(v)){
				this[v]= new RegExp("(?:^|-|\\s+)"+v+"(?:\\s+|-|$)");
			};
			return this[v];
		}
	}
};


compono.prototype = {
	$:function(node){
		if(arguments.length > 1 || ( node && node.length && node.constructor !== String && !node.nodeType )){
			var result = new compono.DOMArray();
			for(var i=0,l=arguments.length; i<l; i++){
				result.push( arguments.callee.call(this, arguments[i]) )
			};
			return result;
		};
		if(node){
			if(typeof(node)=="string"){
				node = document.getElementById(node)
			};
			if(node && node.nodeType && !node.core){
				compono.HTMLElements.implement(node);
			}
		};
		return node
	},
	$$:function(rule,scope,test){	
		return new compono.Selector(rule,scope,test);
	},
	$F:function(o){
		if(!o){
			return arguments.callee.apply(this,this.$T("form"))
		}
		else if(o.nodeType){
			return arguments.callee.call(this,(o.nodeName.toUpperCase()=="FORM"?Array.toArray(o.elements):this.$T("input","textarea","select","button",o)))
		}
		else if(arguments.length>1 || (o.length&&o.constructor!==String)){
			var hash = new compono.Hash();
			Array.toArray((o.length&&o.constructor!==String)?o:arguments).forEach(function(o){
				hash[o.name] = o.value;
			},this);
			return hash
		};
		return this.$(o).value
	},
	$T:function(tag){	
		scope = arguments.length && arguments[arguments.length-1].nodeType ? Array.prototype.pop.call(arguments) : document;
		tag = !tag||tag.nodeType ? "*" : tag;
		if(arguments.length > 1){
			for(var i=0,z=[],a; (a=arguments[i]) && typeof(a)=="string";i++){
				z = z.concat(arguments.callee.call(this,a,scope));
			};
			return z
		}else if(tag&&tag.constructor==Array){
			return arguments.callee.apply(this,tag,scope);
		};
		return Array.toArray(scope.getElementsByTagName(tag))
	},
	$T1:function(tag,scope){
		scope = arguments.length && arguments[arguments.length-1].nodeType ? Array.prototype.pop.call(arguments) : document;
		tag = !tag||tag.nodeType ? "*" : tag;
		var r = scope.getElementsByTagName(tag)
			r = r.length ? r[0] : false;
			return r ? compono.HTMLElements.implement(r) : false;
	},
	$N:function(name){
		if(!name){
			return false
		};
		if(arguments.length>1)
		{
			for(var i=0,result=[],z=arguments.length;i<z;i++)
			{
				result = result.concat(arguments.callee.call(this,arguments[i]))
			};
			return result
		}
		else if(name.constructor == Array)
		{
			return arguments.callee.apply(this,name)
		};
		return Array.toArray(document.getElementsByName(name))
	},
	$A:function(c){
		if(!c){
			return false
		};
		if(c instanceof Array){	
			return c 
		};
		try{
			return Array.prototype.slice.call(c,0);
		}catch(e){
			for(var i=c.length-1,r=[];i>=0;i--){
				r[i]=c[i];
			};
			return r
		}
	},
	$R:function(url,proto){
		var request = new compono.Ajax.Request(url);
		if(proto){
			Object.extend(proto,request);
		};
		return request;
	},
	$U:function(time,url,proto){
		var request = new compono.Ajax.Updater(url,time);
		if(proto){
			Object.extend(proto,request);
		};
		return request;
	},
	$DD:function(b,t,g,c){	return new compono.DragnDrop(b,t,g,c)		},
	$S:function(){			return compono.Storage						},
	$H:function(proto){		return new compono.Hash(proto);				},
	$FX:function(){			return compono.Effects						},
	$E:function(){			return compono.Event						},
	$B:function(){			return compono.Browser	 					},
	$W:function(s){			return compono.Wiki.render(s)				},
	$D:function(c,p){		return new compono.DOMBuilder(c,p)			}
};

Object.extend(compono.prototype, compono);

/** *************************************************************************************************************
  * HTMLElements
  *********************************************************************************************************** **/
compono.HTMLElements = compono.Static({
	implement:function(node){
		if(node&&node.nodeType==1&&!node.core){
			Object.extend(this.Element, node);
			if(this.hasOwnProperty(node.nodeName.toLowerCase())){
				Object.extend(this[node.nodeName.toLowerCase()], node)
			};
			node.core = compono
		};
		return node
	},
	Element:{
		is:function(rule){
			return this.select(rule,this,true);
		},
		attr:function(key,value){
			if(key instanceof Object){
				for(var p in key){
					this.attr(p,key[p])
				};
				return this
			};
			var prop = key in this;
			if(arguments.hasOwnProperty(1)){
				if(prop){
					this[key] = value;
				}else{
					this.setAttribute(key,value);
				};
				return this;
			};
			return prop ? this[key] : this.getAttribute(key);
		},
		first:function(){
			if(this.firstElement){
				return this.firstElement
			};
			var node = this.firstChild;
			while(node && node.nodeType != this.nodeType){
				node = node.nextSibling
			};
			return compono.$(this.firstElement = node);
		},
		firstOfType:function(nodeName){
			if(this.firstOfTypeElement){
				return this.firstOfTypeElement
			};
			var node = this.firstChild, nodeName = (nodeName||this.nodeName).toUpperCase()
			while(node && node.nodeName != nodeName){
				node = node.nextSibling
			};
			return compono.$(this.firstOfTypeElement = node);
		},
		next:function(){
			if(this.nextElement){
				return this.nextElement
			};
			var node = this.nextSibling;
			while(node && node.nodeType != this.nodeType){
				node = node.nextSibling
			};
			if(node){
				node.previousElement = this
			};
			return compono.$(this.nextElement = node)
		},
		nextOfType:function(nodeName){
			if(this.nextOfTypeElement){
				return this.nextOfTypeElement
			};
			var node = this.nextSibling, nodeName = (nodeName||this.nodeName).toUpperCase();
			while(node && node.nodeName != nodeName){
				node = node.nextSibling
			};
			if(node){
				node.previousOfTypeElement = this
			};
			return compono.$(this.nextOfTypeElement = node)
		},
		previous:function(){
			if(this.previousElement){
				return this.previousElement
			};
			var node = this.previousSibling;
			while(node && node.nodeType != this.nodeType){
				node = node.previousSibling
			};
			if(node){
				node.nextElement=this
			};
			return compono.$(this.previousElement = node)
		},
		previousOfType:function(nodeName){
			var node = this.previousSibling, nodeName = (nodeName||this.nodeName).toUpperCase();
			while(node && node.nodeType != this.nodeType && this.nodeName != nodeName){
				node = node.previousSibling
			};
			if(node){
				node.previousOfTypeElement = this
			};
			return compono.$(node)
		},
		last:function(){
			if(this.lastElement){
				return this.lastElement
			};
			var node = this.lastChild;
			while(node && node.nodeType != this.nodeType){
				node = node.previousSibling
			};
			return compono.$(this.lastElement = node)
		},
		lastOfType:function(nodeName){
			if(this.lastOfTypeElement){
				return this.lastOfTypeElement
			};
			var node = this.lastChild, nodeName = (nodeName||this.nodeName).toUpperCase();
			while(node && node.nodeType != this.nodeType && this.nodeName != nodeName){
				node = node.previousSibling
			};
			return compono.$(this.lastOfTypeElement = node)
		},
		parent:function(handler){
			var parent = this.parentNode;
			if(handler)
			{
				while(parent)
				{
					if(handler.call(this, parent) == true){
						return parent
					};
					parent = parent.parentNode;
				}
			};
			return compono.$(parent);
		},
		getChildren:function(formula){
			if((window.attachEvent && !window.opera) || (this.children && !formula))
			{
				return this.children;
			};
			this.children = [];
			var arg = [];
			for(var i=0, l=this.childNodes.length;i<l;i++)
			{
				if(this.childNodes[i].nodeType == 1)
				{
					arg[arg.length] = this.childNodes[i];
				}
			};
			if(this.children&&!formula){
				return this.children=arg;
			};
			return arg;
		},
		append:function(node, handler){
			compono.$( node );
			
			handler = handler || function(){return true};
			
			if(typeof(node) == "string" && /<|>/.test(node) && handler.call(this, node) != false)
			{
				return this.html(node, true);
			}
			if(typeof(node) == "string" && handler.call(this, node) != false)
			{
				return this.appendChild( compono.$( document.createElement( node ) ) );
			}
			else if(node.length && typeof(node) != "string")
			{
				return arguments.callee.call( this, Array.toArray( node ), handler )
			}
			else if(node instanceof Array)
			{
				for(var i=0, arr=[],length = node.length; i < length; i++){
					if(handler.call( this , node[i], node) != false){
						arr.push( this.appendChild( compono.$( node[i] ) ) )
					}
				};
				return arr;
			}
			else if(node.nodeType && handler.call(this, node) != false)
			{
				return this.appendChild(node)
			};
			return this
		},
		remove:function(index){
			if(typeof(index) == "number")
			{
				var children = this.getChildren(true);
				if(index >= 0 && index < children.length){
					this.removeChild( children[index] );
				}
			}
			else if(index == true)
			{
				this.getChildren().forEach(function(child){
					this.removeChild(child);
				},this)
			}
			else
			{
				this.parentNode.removeChild( this );
			};
			return this;
		},
		before:function(node){
			if(typeof(node)=="string"){
				node = document.createElement(node);
			};
			return this.parentNode.insertBefore(compono.$(node), this)
		},
		after:function(node){
			if(typeof(node)=="string"){
				node = document.createElement(node);
			};
			compono.$(node);
			if(this.next()){
				return this.parentNode.insertBefore(node, this.next())
			};
			return this.parentNode.appendChild(node)
		},
		enable:function(v){
			if(v==false){
				this.setAttribute("disabled","disabled");
				this.appendClassName("disabled")
			}else{
				this.removeAttribute("disabled");
				this.removeClassName("disabled")
			};
			return this;
		},
		css:function(p,v){
			if(typeof(p)!="string"){
				var i;
				for(i in p){
					arguments.callee.call(this,i,p[i]);
				}
			};
			if(typeof(v)=="undefined"||typeof(v)=="null"){
				if(document.defaultView&&document.defaultView.getComputedStyle){
					var s = document.defaultView.getComputedStyle(this, "");
					return s[p] || s.getPropertyValue(p);
				}else if(this.currentStyle){
					return this.currentStyle[compono.hash.css.property.get(p)]
				}else{
					return this.style[compono.hash.css.property.get(p)]
				}
			}else{
				this.style[compono.hash.css.property.get(p)] = v
			};
			return this;
		},
		hasClassName:function(_class){
			if(_class && typeof(_class) != "string" && _class instanceof Array){
				return _class.every(arguments.callee,this);
			};
			return compono.hash.css.names.get(_class).test(this.className)
		},
		appendClassName:function(_class, index){
			if(_class && typeof(_class) != "string" && _class instanceof Array){
				return _class.every(arguments.callee,this);
			};
			if(this.hasClassName(_class) == false){
				if(typeof(index) == "number"){ 
					var arr = this.className.split(" ");
						arr[index] = _class;
					this.className = arr.join(" ")
				}else{
					this.className += " " + _class
				}
			};
			return this
		},
		removeClassName:function(_class, index){
			if(_class && typeof(_class) != "string" && _class instanceof Array){
				return _class.every(arguments.callee,this);
			};
			if(this.hasClassName(_class) == true){
				if(typeof(index) == "number"){ 
					var arr = this.className.split(" ");
					delete arr[index];
					this.className = arr.join(" ")
				}else{
					this.className = this.className.replace(compono.hash.css.names.get(_class)," ");
				}
			};
			return this;
		},
		toggleClassName:function(_class, index, force){
			if(_class && typeof(_class) != "string" && _class instanceof Array){
				return _class.every(arguments.callee,this);
			};
			if(typeof(force)!="boolean"){
				force = !this.hasClassName(_class)
			};
			return (force ? this.appendClassName : this.removeClassName).call(this, _class, index);
		},
		show:function(force){
			if(force==false){
				return this.hide()
			};
			this.style.display="block";
			this.appendClassName("show");
			this.removeClassName("hide");
			return this;
		},
		hide:function(force){
			if(force==false){
				return this.show()
			};
			this.style.display="none";
			this.removeClassName("show");
			this.appendClassName("hide");
			return this
		},
		cords:function(){
			var x, y, ax, ay, s, p;
			if(this.offsetParent){
				s=this.offsetParent, p, x=this.offsetLeft||0, ax=0, y=this.offsetTop||0, ay=0;
				while(s){
					x+=s.offsetLeft; ax+=s.scrollLeft;
					y+=s.offsetTop; ay+=s.scrollTop;
					p=s; s=s.offsetParent;
				}
			};
			x=x||0; y=y||0; ax=(x-ax)||0; ay=(y-ay)||0;
			return {left:x, top:y, right:(x+this.offsetWidth), bottom:(y+this.offsetHeight),
					aleft:ax, atop:ay, aright:(ax+this.offsetWidth), abottom:(ay+this.offsetHeight),
					width:this.offsetWidth, height:this.offsetHeight,
					parent:p};
		},
		viewport:function(){
			var b = document.documentElement||document.body;
			return {
				base:b,
				width:(b.clientWidth),
				height:(b.clientHeight),
				totalWidth:(b.scrollWidth),
				totalHeight:(b.scrollHeight)
			}
		},
		cleanWhitespace:function(){
			if(this.childNodes.length>0){
				Array.toArray(this.childNodes).forEach(function(node){
					if(node.nodeType!=1){
						this.removeChild(node)
					}
				},this)
			};
			return this;
		},
		run:function(h){
			if(typeof(h)=="function"){ 
				this.getChildren().forEach(h,this)
			};
			return this;
		},
		select:function(query,scope,test){
			if(query){
				return new compono.Selector(query,scope||this,test||false)
			};
			return false;
		},
		tags:function(q,s){
			return compono.$T(q,s||this);
		},
		event:function(e,h,s){
			compono.Event.add(e,h,s||this);
			return this
		},
		runEvent:function(o,s){
			compono.Event.fire(o,s||this)
			return this;
		},
		removeEvent:function(e,h,s){
			compono.Event.remove(e,h,s||this);
			return this
		},
		load:function(u,o){
			if(u.constructor === String){
				u = new compono.Ajax.Request(u)
			};
			u.onComplete = function(){
				this.node[this.property] = this.response;
			};
			u.property = this.form&&this.type ? "value" : o || "innerHTML";
			if(o){
				Object.extend(o,u)
			};
			u.node = this;
			u.run();
			return this
		},
		bind:function(prop,target){
			//target[prop] = this[prop];
			return this
		},
		blink:function(className,time){
			this.appendClassName(className);
			this.removeClassName.timeout(time||1,this,[className]);
			return this
		},
		html:function(html_text, add){
			if(html_text){
				this.innerHTML = (add?this.innerHTML:"") + html_text;
				return this
			}else{
				return this.innerHTML;
			};
		},
		dom:function(scope,extention){
			if(scope){
				return new compono.DOMBuilder(scope||this,extention);
			};
			return this
		},
		wiki:function(string,add){
			if(string){
				this.html(compono.Wiki.render(string), add)
			};
			return this
		}
	},
	input:{
		serialize:function(json){},
		bind:function(){}
	},
	select:{
		serialize:function(){},
		bind:function(){}
	},
	textarea:{
		serialize:function(){},
		bind:function(){}
	},
	button:{
		serialize:function(){},
		bind:function(){}
	}
});


/** *************************************************************************************************************
  * Collections
  *********************************************************************************************************** **/
compono.DOMArray = function(collection){
	if(collection && collection.constructor && collection.constructor === this.constructor)
	{
		return collection;
	}
	else if(arguments.length==1 && ( collection && collection.constructor === Number && collection > 0))
	{
		this.length	= parseInt(collection,10)
	}
	else if(collection && collection.length >= 0 && !collection.nodeType && collection.constructor !== String)
	{
		this.length = Array.prototype.push.apply(this, Array.toArray(collection))
	}
	else if(collection)
	{
		this.length = Array.prototype.push.apply(this, arguments)
	}
	else
	{
		this.length = 0;
	};
	this.name = "DOMArray";
	this.concat = compono.DOMArray.prototype.concat;
	this.push = compono.DOMArray.prototype.push;
	this.filter = compono.DOMArray.prototype.filter;
	this.map = compono.DOMArray.prototype.map;
	this.first = compono.DOMArray.prototype.first;
	this.last = compono.DOMArray.prototype.last;
	this.next = compono.DOMArray.prototype.next;
	this.previous = compono.DOMArray.prototype.previous;
	return this
};

compono.DOMArray.prototype = new Array;
compono.DOMArray.prototype.constructor = compono.DOMArray;
compono.DOMArray.prototype.concat = function(){
	var d = new this.constructor();
		this.constructor.apply(d, arguments)
		Array.prototype.push.apply(d, Array.prototype.slice.call(this, 0));
	return d;
};
compono.DOMArray.prototype.push = function(){
	this.constructor.apply(this, arguments);
	return this.length;
};
compono.DOMArray.prototype.map = function(h, o){
	if(typeof(h) != "function"){ return false; };
	var r=new this.constructor(), o=o||window;
	for(var i=0,z=this.length;i<z;i++){
		if(i in this){
			r.push(	h.call(o,this[i],i,this) || this[i]	);
		}
	};
	return r;	
};
compono.DOMArray.prototype.filter = function(h, o){
	if(typeof(h) != "function"){ return false; };
	var r=new this.constructor(), o=o||window;
	for(var i=0,z=this.length;i<z;i++){
		if(i in this && h.call(o,this[i],i,this)){
			r.push(this[i]);
		}
	};
	return r;
};
compono.DOMArray.prototype.first = function(){
	return compono.$( Array.prototype.first.call(this) );
};
compono.DOMArray.prototype.last = function(){
	return compono.$( Array.prototype.last.call(this) );
};
compono.DOMArray.prototype.next = function(){
	return compono.$( Array.prototype.next.call(this) );
};
compono.DOMArray.prototype.previous = function(){
	return compono.$( Array.prototype.previous.call(this) );
};







/** *************************************************************************************************************
  * Browser
  *********************************************************************************************************** **/
compono.Browser = compono.Static({
	agent:navigator.userAgent.toLowerCase(),
	mac:/mac/i.test(navigator.userAgent),
	win:!( /mac/i.test(navigator.userAgent) ),
	winax:!!( window.ActiveXObject ),
	w3c:!!( document.getElementById ),
	iex:!!( document.all ),
	ns4:!!( document.layers ),
	images:!!( document.images ),
	ce:!!( document.createElement ),
	opera:!!(document.all&&window.opera),
	safari:!!(true),
	firefox:!!(true),
	xpath:!!(document.evaluate),
	document:( document.documentElement||document.body.parentNode),
	body:((document.documentElement||document.body.parentNode).body)
});

if(window.attachEvent&&!window.opera){
	compono.Browser.attributes={
		"opacity":{p:"filter",v:"alpha(opacity={value})"},
		"class":"className",
		"for":"htmlFor",
		"style":"cssText"
	}
}else{
	compono.Browser.attributes={}
}


/** *************************************************************************************************************
  * Event
  *********************************************************************************************************** **/
compono.Event = compono.Static({
	name:"Event",
	isEvent:function(eventName)
	{
		return /^(abort|blur|change|error|focus|load|reset|resize|scroll|select|beforeunload|submit|unload|key|click|dbl|mouse|DOM)/i.test(eventName);
	},
	add:function(eventName, $function, object, bubble)
	{
		if( this.isActionEvent(eventName, $function, object) )
		{
			var c = this.createActionEvent(eventName, $function, object);
			eventName = c.e;
			$function = c.f;
		}
		else if( this.isObjectEvent(eventName, $function, object) )
		{
			return this.createObjectEvent(eventName, $function, object);
		}
		else if( this.isKeyEvent(eventName, $function, object) )
		{
			var c = this.createKeyEvent(eventName, $function, object);
			eventName = c.e;
			$function = c.f;
		};
		if(object.attachEvent && !window.opera)
		{
			/* Keep the function binded to its node because it needs to be removed after */
			object.EventBind = object.EventBind || {};
			object.EventBind[eventName] = object.EventBind[eventName] || {};
			$function.EVENTBINDUNIQUEID = $function.EVENTBINDUNIQUEID || (Math.random()*1000);

			var EventBind;
			if( object.EventBind[eventName].hasOwnProperty( $function.EVENTBINDUNIQUEID ) == false )
			{
				object.EventBind[ eventName ][ $function.EVENTBINDUNIQUEID ] = function(e){ 
					var f=arguments.callee; 
						f.func.call( f.scope, f.base.compatible(e) ); 
				};
			};
			
			EventBind = object.EventBind[ eventName ][ $function.EVENTBINDUNIQUEID ];
			EventBind.base = this;
			EventBind.scope = object;
			EventBind.func = $function;
			EventBind.toString = function(){	
				return this.func.toString();
			};
			
			return object.attachEvent("on"+eventName, EventBind)
		}
		else if( object.addEventListener )
		{
			return object.addEventListener(eventName, $function, bubble || false)
		}
		else
		{
			object["on"+eventName] = $function;
			return true
		};
		return false
	},	
	remove:function(eventName, $function, object, bubble)
	{
		if( this.isActionEvent(eventName, $function, object, bubble) )
		{
			var c = this.createActionEvent(eventName, $function, object, bubble);
			eventName = c.e;
			$function = c.f;
		}
		else if( this.isObjectEvent(eventName, $function, object, bubble) )
		{
			return this.removeObjectEvent(eventName, $function, object, bubble)
		}
		else if( this.isKeyEvent(eventName, $function, object, bubble) )
		{
			var c = this.removeKeyEvent(eventName, $function, object, bubble);
			eventName = c.e;
			$function = c.f;
		};
		
		if( object.detachEvent && !window.opera )
		{
			object.EventBind = object.EventBind || {};
			object.EventBind[eventName] = object.EventBind[eventName] || {};
			$function.EVENTBINDUNIQUEID = $function.EVENTBINDUNIQUEID || (Math.random()*1000);

			if( object.EventBind[eventName].hasOwnProperty( $function.EVENTBINDUNIQUEID ) )
			{
				object.detachEvent("on"+eventName, object.EventBind[eventName][ $function.EVENTBINDUNIQUEID ] );
				delete object.EventBind[eventName][ $function.EVENTBINDUNIQUEID ];
			}
			else
			{
				object.detachEvent("on"+eventName, $function);
			};
			return true
		}
		else if(object.removeEventListener)
		{
			object.removeEventListener( eventName, $function, bubble || false );
			return true
		}
		else
		{
			object["on"+eventName] = null;
			return true
		};
		return false
	},
	compatible:function(event)
	{
		if(window.addEventListener){
			return event;
		};
		
		event.preventDefault = function(){
			return this.returnValue = false
		};
		event.stopPropagation = function(){
			return this.cancelBubble = true
		};
		
		/*IE does not support the target (srcElement==currentTarget), so target is equal to currentTarget even when bubbling events*/
		/*on Gecko, currentTarget is the obj where the event is taking place now (may not be the original due to capturing/bubling)*/
		event.currentTarget = event.srcElement;
		event.target = event.srcElement && !event.target ? event.srcElement : event.target;
		event.relatedTarget = ((event.toElement || event.fromElement) && !event.relatedTarget) ? (event.toElement || event.fromElement) : event.relatedTarget;
		
		event.which = event.keyCode; /*keyCode is always available in IE*/
		event.charCode = (event.type.toLowerCase() == "keypress") ? event.keyCode : 0; /*create a charCode behavior*/
		event.character = String.fromCharCode(event.charCode); /*CUSTOM PROPERTY*/
		event.isChar = (event.charCode > 0);

		event.pageX = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
		event.pageY = event.clientY + document.body.scrollTop + document.documentElement.scrollTop;

		event.cancelable = true; /*on IE all events are cancelable*/
		event.timeStamp = new Date().getTime();
		event.eventPhase = 2; /*only bubbling on IE*/
		
		return event;
	},
	implement:function(object)
	{
		object.event = function(eventName, $function, scope){
			return this.Event.add(eventName, $function, scope||this);
		};
		object.removeEvent = function(eventName, $function, scope){
			return this.Event.remove(eventName, $function, scope||this);
		};
		object.runEvent = function(){
			return this.Event.fire.apply(this.Event, arguments);
		};
	},
	/** *****************************************************************************************
	 * Creates a shortcut event
	 * @param {String} eventName Event name can be keys together (CTRL+ALT+SHIFT+K);
	 * @param {Function} $function Handler that will be executed on trigger event;
	 * @param {Object, Node} scope Node or Object that will be the event scope;
	 * *************************************************************************************** **/
	defaultKeyEvent:"keydown",
	isKeyEvent:function(eventName, $function, scope)
	{
		return !this.isEvent(eventName);
	},
	createKeyEvent:function(eventName, $function, scope)
	{
		var code="", group={};
		if(this.KEYGROUPS.hasOwnProperty(eventName)){
			group = this.KEYGROUPS[eventName];
			code = "f.group.hasOwnProperty(event.keyCode)";
		}else{
			var amp="";
			eventName.split("+").forEach(function(key){
				switch(key.toUpperCase()){
					case "CTRL":	code += amp + "event.ctrlKey"; break;
					case "ALT":		code += amp + "event.altKey"; break;
					case "SHIFT":	code += amp + "event.shiftKey"; break;
					default:		code += amp + "event.keyCode==" + this.findKeyCode(key); break;
				};
				amp = "&&";
			})
		};
		$function.KeyEventBind = new Function("event","var f=arguments.callee; if(" + code + "){f.base.compatible(event); return f.func.call(f.scope, event, f.group[event.keyCode]);}");
		$function.KeyEventBind.scope = scope;
		$function.KeyEventBind.group = group;
		$function.KeyEventBind.func = $function;
		$function.KeyEventBind.base = this;
		return {e:this.defaultKeyEvent, f:$function.KeyEventBind};
	},
	removeKeyEvent:function(eventName, $function)
	{
		delete $function.KeyEventBind;
		return {e:this.defaultKeyEvent, f:$function};
	},
	findKeyCode:function(key)
	{
		var a, b, group=this.KEYGROUPS;
		for(a in group){
			for(b in group[a]){
				if(group[a][b] == key){
					return b;
				}
			}
		}
	},
	/** *****************************************************************************************
	 * Creates a event that catches
	 * @param {String} eventName Event name can be keys together (CTRL+ALT+SHIFT+K);
	 * @param {Function} $function Handler that will be executed on trigger event;
	 * @param {Object, Node} scope Node or Object that will be the event scope;
	 * *************************************************************************************** **/
	defaultActionEvent:"click",
	isActionEvent:function(eventName, $function, object)
	{
		return eventName && eventName.substr(0,1) == "#";
	},
	createActionEvent:function(eventName, $function, object)
	{
		$function.ActionEventBind = function(e){
			var c = arguments.callee;
			var a = c.base.$(c.base.compatible(e).target);
			var attr = a.attr("action")||a.attr("href")||a.href;
			if(attr&&attr.length){
				var action = attr.substr(attr.lastIndexOf("#")).substr(1);
				if(c.action==true||c.action==action){
					e.action=action;
					return c.func.call(c.object,e);
				}
			}
		};
		$function.ActionEventBind.base = this;
		$function.ActionEventBind.action = eventName.substr(1) || true;
		$function.ActionEventBind.func = $function;
		$function.ActionEventBind.object = object;
		
		return {e:this.defaultActionEvent, f:$function.ActionEventBind};
	},
	removeActionEvent:function(eventName, $function, object)
	{
		delete $function.ActionEventBind;
		return {e:this.defaultActionEvent, f:$function};
	},
	isObjectEvent:function(eventName, $function, object)
	{
		return !object.nodeType && object !== window;
	},
	createObjectEvent:function(eventName, $function, object)
	{
		if(!object.eventListener){
			object.eventListener = {}
		};
		if(!object.eventListener.hasOwnProperty(eventName)){
			objectob.eventListener[eventName] = []
		};
		object.eventListener[eventname].push($function);
		return true;
	},
	removeObjectEvent:function(eventName, $function, object)
	{
		if(object.eventListener && object.eventListener.hasOwnProperty( eventName )){
			object.eventListener.forEach(function(fu, i){
				if(fu === $function) delete object.eventListener[i]
			},this)
		};
		return true;
	},
	create:function(type)
	{
		var n, g, label, args, e;
		for(n in this.EVENT_CLASSES){
			g = this.EVENT_CLASSES[n];
			if(g[1].test(type)){
				label = g[0];
				args = g[2];
				break
			}				
		};
		args = arguments.length < args.length ? args.map(function(o,i){ return this[i]||o },arguments) : arguments;
		e = document.createEvent(n)
		if(e){
			e[label].apply(e,args);
		};
		return e
	},
	fire:function(eventName, object, event)
	{
		if( !object.nodeType ){
			if(object.eventListener && object.eventListener.hasOwnProperty( eventName )){
				event = event || {};
				event.type = eventName;
				return object.eventListener[ eventname ].every(function(fu){
						return fu.call(object, event)!=false
					},this)
			}
		};
		if(object.dispatchEvent){
			return object.dispatchEvent( this.create(eventName) )
		}else if( object.fireEvent ){
			return object.fireEvent( "on"+eventName )
		}else{
			var fu = object["on"+eventName];
			if(fu && typeof(fu) == "function"){
				fu.call(object)
			}
		}
	},
	KEYGROUPS:{
		UP:{38:"UP"},
		TAB:{9:"TAB"},
		ESQ:{27:"ESQ"},
		END:{35:"END"},
		HELP:{112:"F1"},
		DOWN:{40:"DOWN"},
		HOME:{36:"HOME"},
		LEFT:{37:"LEFT"},
		SPACE:{32:"SPACE"},
		RIGHT:{39:"RIGHT"},
		ENTER:{13:"ENTER"},
		INSERT:{45:"INSERT"},
		DELETE:{46:"DELETE"},
		PAGEUP:{33:"PAGEUP"},
		PAGEDOWN:{34:"PAGEDOWN"},
		BACKSPACE:{8:"BACKSPACE"},
		ARROWS:{37:"LEFT",38:"UP",39:"RIGHT",40:"DOWN"},
		MATHOPERATORS:{106:"*",107:"+",109:"-",111:"/"},
		MATHNUMBERS:{96:"0",97:"1",98:"2",99:"3",100:"4",101:"5",102:"6",103:"7",104:"8",105:"9"},
		FUNCTIONS:{112:"F1",113:"F2",114:"F3",115:"F4",116:"F5",117:"F6",118:"F7",119:"F8",120:"F9",121:"F10",122:"F11",123:"F12"},
		CHARACTERS:{65:"A",66:"B",67:"C",68:"D",69:"E",70:"F",71:"G",72:"H",73:"I",74:"J",75:"K",76:"L",77:"M",78:"N",79:"O",80:"P",81:"Q",82:"R",83:"S",84:"T",85:"U",86:"V",87:"W",88:"X",89:"Y",90:"Z"},
		NUMBERS:{48:"0",49:"1",50:"2",51:"3",52:"4",53:"5",54:"6",55:"7",56:"8",57:"9",96:"0",97:"1",98:"2",99:"3",100:"4",101:"5",102:"6",103:"7",104:"8",105:"9"}
	},
	/*http://www.howtocreate.co.uk/tutorials/javascript/domevents*/
	EVENT_CLASSES:{
		"MouseEvents":["initMouseEvent",/click|mousedown|mousemove|mouseout|mouseover|mouseup/i,["type",true,true,window,0,0,0,0,0,false,false,false,false,0,null]],
		"UIEvents":["initUIEvent",/DOMActivate|DOMFocusIn|DOMFocusOut|keydown|keypress|keyup/i,["type",true,true,window,1]],
		"HTMLEvents":["initEvent",/abort|blur|change|error|focus|load|reset|resize|scroll|select|submit|unload/i,["type",true,true]],
		"KeyEvents":["initKeyEvent",/keydown|keypress|keyup/i,['type',true,true,window,false,false,false,false,13,0]]
	}
});

/** *************************************************************************************************************
  * FileLoader
  *********************************************************************************************************** **/
compono.FileLoader = compono.Class({
	name:"FileLoader",
	files:{},
	root:(document.getElementsByTagName('head')[0]),
	constructor:function(collection)
	{
		if(collection)
		{
			if(collection.nodeType == 1)
			{
				collection = collection.childNodes;
			};

			for(var i = collection.length-1; i>=0; i-- )
			{
				if( collection[i].nodeType == 1 )
				{
					this.add( collection[i].type, collection[i].href || collection[i].src);
				}
			}
		}
	},
	add:function(type,src)
	{
		var node;
		if(!type || !src)
		{
			return false;
		};
		
		switch(type)
		{
			case "js":
			case "javascript":
			case "text/javascript":
				node = document.createElement("script");
				node.setAttribute("type",type);
				node.setAttribute("src",src);
				break;
			case "css":
			case "text/css":
			case "stylesheet":
				node = document.createElement("link");
				node.setAttribute("type",type);
				node.setAttribute("href",src);
				node.setAttribute("rel","stylesheet");
				break;
		};
		
		return this.root.appendChild( node );
	},
	append:function(type,src)
	{
		this.files[src] = {type:type, src:src, node:null};
	},
	remove:function(type,src){
		var file;
		if((file = this.files[src]))
		{
			this.root.removeChild(file);
		}
	},
	load:function(){
		var file, i;
		for(i in this.files)
		{
			file = this.files[i];
			file.node = this.add(file.type, file.src);
		}
	}
});


/** *************************************************************************************************************
  * Ajax
  *********************************************************************************************************** **/
compono.Ajax = compono.Class({
	name:"Ajax",
	returnType:"text/plain",
	running:false,
	TIMEOUT_ID:-1,
	READY_STATE:0,
	type:"REQUEST",	
	method:"POST",
	postBody:"",
	response:{},
	request:{},
	async:true,
	timeout:0,
	url:"",
	executionError:false,
	event:function(){
		if(!this.hasOwnProperty(arguments[0]))
			return; 
		var name = Array.prototype.shift.call(arguments);
		return this[name].apply(this,arguments);
	},
	abort:function(){
		if(this.event("onAbort",false)!=false){
			//http://www.quirksmode.org/blog/archives/2005/09/xmlhttp_notes_a_1.html
			this.request.abort();
			this.running = false;
		}
	},
	//*****************************************************************	TIMEOUT
	setTimeout:function(t, call){
		return this.TIMEOUT_ID = this.abortTimeout.timeout((t||this.timeout),this,[],function(){
					return this.event("onTimeout",false);
				})
	},
	abortTimeout:function(){
		this.abort();
		this.clearTimeout();
	},
	clearTimeout:function(){
		window.clearTimeout(this.TIMEOUT_ID);
		this.TIMEOUT_ID = -1;
	},
	
	
	constructor:function(){
		
	},
	
	//*****************************************************************	PARAMETROS
	paramsHash:false,
	addParam:function(p,v){
		if(this.paramsHash==false){
			this.paramsHash = {};
		};
		if(typeof(p) == "string" || typeof(p) == "number"){
			this.paramsHash[p] = v;
		}else{
			this.paramsHash = p;
		};
		return this.paramsHash;
	},
	removeParam:function(p){
		if(!p){ 
			this.paramsHash = {};
		}else{
			delete this.paramsHash[p];
		};
		return this.paramsHash;
	},
	paramsToString:function(){
		if(this.paramsHash instanceof compono.Hash){
			return this.paramsHash.toQueryString();
		};
		//encodeURIComponent
		return (new String().toQueryString(this.paramsHash));	
	},
	
	//*****************************************************************	HEADERS
	headerHash:false,
	addHeader:function(p,v){
		if(this.headerHash==false){
			this.headerHash={	
				"Content-Type":"text/plain", "encoding":"UTF-8",
				"AjaxApp":"COMPONO", "AjaxAppVersion":(compono.version.toString())
			}
		};
		if(typeof(p) == "string" || typeof(p) == "number"){
			this.headerHash[p] = v;
		}else{
			this.headerHash = p;
		};
		return this.headerHash;
	},
	removeHeader:function(p){
		if(!p){
			this.headerHash = {};
		}else{
			delete this.headerHash[p];
		};
		return this.headerHash;
	},
	resolveHeaderToRequest:function(http){
		if(this.method.toUpperCase() == "POST"){
			if(!this.headerHash.hasOwnProperty("Content-Type")){ 		this.addHeader("Content-Type","application/x-www-form-urlencoded") }
			if(!this.headerHash.hasOwnProperty("Content-length")){		this.addHeader("Content-length",(this.paramsHash.toString().length)) }
			if(!this.headerHash.hasOwnProperty("Connection")){ 			this.addHeader("Connection","close") }
		};
		for(var i in this.headerHash){
			http.setRequestHeader(i, "");
			http.setRequestHeader(i, this.headerHash[i]);
		}	
	},
	run:function(url,timeout){
		if(this.running){
			this.abort();
		};
		this.request = this.XMLHTTP();
		var req = this.request;
		var u = url||this.url||window.location.href;
		var b=null;
		var o=this;
		switch(this.method.toUpperCase()){
			case "GET":	
				if(this.paramsToString().length){
					u+=(u.indexOf("?")==-1?'?':'&')+this.paramsToString(); 
				}
				break;
			case "HEAD":
			case "POST": 
			default:
				b = this.postBody||this.paramsToString(); 
				break;
		};
		this.running = true;
		if(this.event("onRun")==false){
			return false
		};
		req.onreadystatechange = function(){
			o.XMLHTTPPROCESS.call(o, req)
		};
		req.open(this.method, u, this.async);
		
		this.resolveHeaderToRequest(req);
		
		if(req.overrideMimeType){
			req.overrideMimeType( this.returnType );
		};
		
		if(this.timeout||timeout){
			if(this.TIMEOUT_ID>-1){
				this.clearTimeout()
			};
			this.setTimeout(timeout);
		};
		req.send(b);
		return this;
	},	
	send:function(b){
		this.request.send(b||this.postBody||this.paramsToString());
		return this;
	},
	filterResponse:function(mime){
		return this.filters[(( mime ? mime.toLowerCase() : false ) || "text/plain" )].call(this, this.request);
	},
	filters:{
		"text/javascript":function(c)
		{	
			if(this.request.responseText.length){
				return this.request.responseText.toString().toJSON(this);
			};
			return null;
		},
		"application/json":function(c)
		{
			if(this.request.responseText.length){
				return this.request.responseText.toString().toJSON(this);
			};
			return null;
		},
		"text/plain":function(c)
		{
			return c.responseText;	
		},
		"text/xml":function(c)
		{
			return c.responseXML;	
		},
		"text/html":function(c)
		{
			var b = document.createElement("div");
				b.innerHTML=c.responseText;
				return b.firstChild;	
		},
		"text/wiki":function(c)
		{
			return compono.Wiki.render(c) 
		}
	},
	PROVIDERS:["MSXML2.XMLHttp.6.0","MSXML2.XMLHTTP.5.0","MSXML2.XMLHTTP.4.0","MSXML2.XMLHTTP.3.0","MSXML2.XMLHTTP","MSXML.XMLHttp","Microsoft.XMLHTTP"],
	XMLHTTP:function(){
		var r;
		if(window.XMLHttpRequest){
			r = new XMLHttpRequest();
		}else if(window.ActiveXObject){
			r = this.PROVIDERS.test(function(n){
					return new window.ActiveXObject(n);
				})
		};
		return r;
	},
	XMLHTTPPROCESS:function(http){
		if(this.READY_STATE == http.readyState){ 
			return;
		};
		switch(http.readyState){
			case 0: this.event("onUnInitialized",http); break;
			case 1:	this.event("onLoading",http); break;
			case 2:	this.event("onLoaded",http); break;
			case 3:	this.event("onInteractive",http); break;
			case 4:
				try{
					var s = http.status;
					this.running = false;
					switch(s){
						case 0:
						case 200: //SUCCESS;
							this.response = this.filterResponse(this.returnType); 
							this.event("onSuccess",this.response);
							this.event("onComplete",this.response);
							break;
						case 408: //TIMEOUT http://www.checkupdown.com/status/E408.html
						case 504:	
							var r;
							if(this.event("onTimeout",this.response,true) == false){
								r = false;
							};
							this.event("onError",{name:"TimeoutError",status:s});
							return r;
							break;
						case 552: //ABORT
							if(this.event("onAbort",true)!=false){
								http.abort(); 
							};
							this.event("onError",{name:"AbortError",status:s});
							break;
						default:
							this.event("onError",{name:"GeneralError",status:-1});
					}
				}catch(error){
					this.event("onError",error);
					this.executionError = true;
				};
				this.clearTimeout();
				break;
		};
		this.READY_STATE = http.readyState;
	},
	getFormData:function(form,e){
		var str=[];
		
		for( var i=0, o, l=form.elements.length; i<l; i++){	
			o = form.elements[i]
			if(!o.disabled){
				switch(o.nodeName.toLowerCase()){
					case "input":
						switch(o.type.toLowerCase()){
							case "radio":
							case "checkbox":
								if(o.checked){
									str.push(o.name + "=" + o.value);
								};
								break;
							case "button":
							case "submit":
							case "reset":
								continue; break;
							default:
								str.push(o.name + "=" + o.value);
						}
						break;
					case "select":
						if(o.multiple){
							for(var z=0;z<o.options.length;z++){
								if(o.options[z].selected){
									str.push(o.name + "=" + o.options[z].value);
								}
							}
						}else{
							str.push(o.name + "=" + o.value);
						};
						break;
					case "button": 
						continue; break;
					default:
						str.push(o.name + "=" + o.value);
						break;
				}
			}
		};
		
		submit = e.explicitOriginalTarget || e.relatedTarget || document.activeElement || false;
		if(submit){
			str.push(submit.name + "=" + submit.value);
		};
		
		return str.join("&")
	}
});

compono.Ajax.Request = compono.Ajax.Class({
	type:"Request",
	constructor:function(url){
		this.url=url||window.location.href;
	}
});

compono.Ajax.Binder = compono.Ajax.Class({
	type:"Binder",
	property:false,
	scope:false,
	value:false,
	server:false,
	constructor:function(scope,prop,url){
		this.scope = scope;
		this.property = prop||"value";
		this.url = url||window.location.href;
		this.watchOnScope.scope = this;
		scope.watch(this.property,this.watchOnScope);
		this.watch("value",this.watchOnObject);
		this.server = new this.base.Ajax.Updater();
		this.server.base = this;
		this.server.onComplete = function(){
			this.base.watchOnServer(this.response)
		};
		this.server.run(url);
	},
	watchOnScope:function(v){
		this.server.addParam("property",v);
		this.server.send();
		return arguments.callee.scope.value = v;
	},
	watchOnObject:function(v){
		this.server.addParam("property",v);
		this.server.send();
		this.scope.value = v;
		return this.value = v;
	},
	watchOnServer:function(v){
		if(this.event("onChange",v)==false){
			return false;
		};
		this.set(v);
	},
	event:function(e){
		//Array.toArray(arguments).pop();
		return e;
	},
	get:function(){
		return this.value;
	},
	set:function(v){
		this.value = v;
	}
});

compono.Ajax.Updater = compono.Ajax.Class({
	type:"Updater",
	hasProgress:false,
	progress:0,
	time:0,
	url:false,
	constructor:function(time,url){
		this.url=url||window.location.href;
		this.time=time||1;
		this.execProgress = function()
		{
			if(this.executionError)
			{
				arguments.callee.interval(false);
			};
			
			if(this.progress && this.progress < 100)
			{
				return this.base.prototype.run.apply(this,arguments);
			}
			else
			{
				this.execProgress.interval(false);
			}
		};
		this.exec = function()
		{
			if(this.executionError)
			{
				arguments.callee.interval(false);
			};
			return this.base.prototype.run.apply(this,arguments);
		};
	},
	stop:function(){
		this.exec.interval(false);
		return this;
	},
	run:function(){
		if(this.hasProgress){
			this.execProgress.interval(this.time, this, arguments);
		}else{
			this.exec.interval(this.time, this, arguments);
		};
		return this;
	}
});

/** *************************************************************************************************************
  * DragnDrop
  *********************************************************************************************************** **/
compono.DragnDrop = compono.Class({
	name:"DragnDrop",
	constructor:function(elements,targets,cType){
		this.elements = elements;
		this.targets = targets;
		this.collisionType = cType||this.collisionType;
	},
	
	useGhostElement:true,
	ghostElement:"",
	
	useMouseElement:true,
	mouseElement:"",
	
	useTargetElement:true,
	targetElement:"",
	
	getBaseTrigger:function(){	return this;},
	position:'absolute',
	state:{p:'',x:0,y:0,z:0},
	grid:0,
	zIndex:1000,

	elements:false,
	targets:[],

	colliders:[],
	oldColliders:[],

	revert:false,
	event:function(){
		if(!this.hasOwnProperty(arguments[0])){
			return; 
		};
		var n = Array.prototype.shift.call(arguments);
		return this[n].apply(this,arguments);
	},
	start:function(event)
	{
		var dragnDrop = this.DragnDrop, node = this.elements;
		node.DragnDrop = dragnDrop;
		
		dragnDrop.move.elements = node;
		dragnDrop.stop.elements = node;
		
		if(window.attachEvent && !window.opera){
			document.body.onselectstart = function(){return false};
			node.onselectstart = null;
		};
		
		node.event("mousemove", dragnDrop.move, document);
		node.event("mouseup", dragnDrop.stop, document);			
		
		if( dragnDrop.event("onDrag") == false ){
			return false;
		}
		
		dragnDrop.state.p = node.css("position");
		dragnDrop.state.x = node.offsetLeft;
		dragnDrop.state.y = node.offsetTop;
		//dragnDrop.state.z = node.css("z-index");
		
		node.css('position', dragnDrop.position);
		//b.style.zIndex = d.zIndex;
		
		node.offsetLeftGap = (event.clientX - node.offsetLeft);
		node.offsetTopGap = (event.clientY - node.offsetTop);
		
		node.appendClassName("dragging");
		
		return this;
	},
	move:function(event)
	{
		var node = arguments.callee.elements;
		
		if( node.DragnDrop.event("onMove") == false){
			return false;
		};
		
		//if(o.DragnDrop.hitTest(o,e)){
			node.style.top = (event.clientY - node.offsetTopGap)+"px";
			node.style.left = (event.clientX - node.offsetLeftGap)+"px";
		//}
		// if(o.DragnDrop.constrain){
			// if(!o.DragnDrop.constructor.collision.type.boundingBox(o,o.DragnDrop.constrain)){
				// o.style.top=(o.oldOffSetTop)+"px";
				// o.style.left=(o.oldOffSetLeft)+"px";
			// }
		// }
		// o.oldOffSetTop = o.offsetTop;
		// o.oldOffSetLeft = o.offsetLeft;
	},
	stop:function(event)
	{
		var node = arguments.callee.elements;
		var dragnDrop = node.DragnDrop;
		
		node.removeEvent("mousemove", dragnDrop.move, document);
		node.removeEvent("mouseup", dragnDrop.stop, document);
		
		if(window.attachEvent && !window.opera){
			document.body.onselectstart = null;
		};
		
		if(dragnDrop.event("onDrop", !!( dragnDrop.colliders.length ) , dragnDrop.colliders, event) == false){
			return false
		};
		
		if(dragnDrop.revert){
			dragnDrop.revertToBeggin( node )
		};
		
		node.removeClassName("dragging");
	},
	run:function(targets,getBaseTrigger,collisionType)
	{
		var elements = this.elements.length && typeof(this.base)!="string" ? this.elements : [this.elements];
		var trigger = getBaseTrigger || this.getBaseTrigger;
		elements.forEach(function(b){
			b.trigger = this.$(trigger.call(this,b));
			b.trigger.elements = this.$(b);
			b.trigger.DragnDrop = this;
			b.trigger.unselectable="on";
			b.trigger.style.MozUserSelect="none";
			b.trigger.style.KhtmlUserSelect="none";
			b.trigger.event("mousedown",this.start);			
		},this);
		
		if(targets){
			this.targets = targets;
		};
		
		this.setHitTest(collisionType);
		return this;
	},
	
	collisionType:"edgebox",
	hitTest:function(){},
	setHitTest:function(collisionType){
		
		if(this.targets){
			this.hitTest = (this.targets.length>=0 && typeof(this.targets)!="string") ? this.collision.manyTargets : this.collision.oneTarget;
		}else{
			this.hitTest = this.collision.nonTarget;
		}
		
		if(typeof(collisionType)=="string"&&this.collision.type.hasOwnProperty(collisionType.toLowerCase())){
			
			this.collisionType = collisionType;
			this.hitTest.type = this.collision.type[this.collisionType.toLowerCase()];
		
		}else if(typeof(collisionType)=="function"){
			
			this.collisionType = "CUSTOM";
			this.hitTest.type = collisionType;
			
		}
		
		return this;
	},	
	revertToBeggin:function(o){
		if(this.event("onRevert",o)==false){
			return false;
		}
		o.style.position = this.state.p;
		o.style.zIndex = this.state.z;
		o.style.left = this.state.x;
		o.style.top = this.state.y;	
		return true;
	},
	collision:{
		nonTarget:function(a,e){},
		oneTarget:function(a,e){
			this.colliders=[];
			if(a !== this.targets){
				if(arguments.callee.type(a,this.targets)){
					this.colliders[this.colliders.length] = this.targets;
					if(this.onCollide){
						this.onCollide(a,this.targets,e);
					}
				}else if(this.onNotCollide){
					this.onNotCollide(a,this.targets,e);
				}
			}
		},
		manyTargets:function(a){
			this.colliders=[];
			this.oldColliders=[];
			for(var i=0,o,z=this.targets.length;i<z;i++){
				o = this.targets[i];
				if(a!==o && arguments.callee.type(a,o)){
					this.colliders[this.colliders.length] = o;
				}else{
					this.oldColliders[this.oldColliders.length] = o;
				}
			};
			if(this.onCollide&&this.colliders.length){
				this.onCollide(a,this.colliders,e);
			};
			if(this.onNotCollide&&this.oldColliders.length){
				this.onNotCollide(a,this.oldColliders,e);
			}
		},
		type:{
			/*When the box touch his target*/
			"edgebox":function(a,b){
				return !(	a.offsetLeft + a.offsetWidth < b.offsetLeft || 
							a.offsetLeft > b.offsetLeft + b.offsetWidth || 
							a.offsetTop + a.offsetHeight < b.offsetTop || 
							a.offsetTop > b.offsetTop + b.offsetHeight		);
			},
			/*When the box is totally inside of his target*/
			"boundingbox":function(a,b){
				return (	a.offsetLeft > b.offsetLeft && 
							a.offsetLeft + a.offsetWidth < b.offsetLeft + b.offsetWidth && 
							a.offsetTop + a.offsetHeight < b.offsetTop + b.offsetHeight && 
							a.offsetTop > b.offsetTop		);
			},
			/*When the box is totally outside of his target*/
			"externalbox":function(a,b){
				return (	a.offsetLeft + a.offsetWidth < b.offsetLeft || 
							a.offsetLeft > b.offsetLeft + b.offsetWidth || 
							a.offsetTop + a.offsetHeight < b.offsetTop || 
							a.offsetTop > b.offsetTop + b.offsetHeight		);
			}
		}
	}
});


/** *************************************************************************************************************
  * DOMBuilder
  *********************************************************************************************************** **/
compono.DOMBuilder = compono.Class({
	name:"DOMBuilder",
	constructor:function(c,p){
		this.container = c;
		this.proto = p||false;
		this.attributes = this.$B().attributes;
	},
	attributes:{},
	buffer:false,
	setAttribute:function(node,attr){
		for(var a in attr){
			node.setAttribute(this.getAttribute(a), attr[a]);
		}
	},
	getAttribute:function(a){
		return this.attributes.hasOwnProperty(a) ? this.attributes[a] : a;
	},
	createPath:function(n){
		//creating path;
		var o = n.parentNode;
		var id = (n.id || (n.className.length ? n.className.split(" ")[0] : false) || n.nodeName);
		if(o[id]){
			if(o[id] instanceof Array){
				o[id].push(n);
			}else{
				o[id] = [o[id],n];
			}
		}else{
			o[id] = n;
		};
		return this;
	},
	render:function(c){
		this[(this.buffer.id||this.buffer.className||this.buffer.nodeName)] = this.buffer;
		if(c==false){
			return this.buffer;
		};
		return (c||this.container||document.body).appendChild(this.buffer);
	},
	NODE:function(){
		var o = document.createElement(Array.prototype.shift.call(arguments)), id="";
		if(this.proto){
			Object.extend(this.proto,o);
		};
		for(var i=0,n;n = arguments[i];i++){
			if(n.nodeType){
				o.appendChild(n);
				this.createPath(n);
			}
			else if(typeof(n) == "string"){
				o.appendChild(document.createTextNode(n));
			}
			else if(n instanceof Object){
				this.setAttribute(o,n);
			}
		};
		return this.buffer=o;
	},
	initialize:function(){
		var s = "A,ABBR,ACRONYM,ADDRESS,BLOCKQUOTE,BR,BUTTON,CITE,CODE,DD,DEL,DFN,DIV,DL,DT,EM,FIELDSET,FORM,H1,H2,H3,H4,H5,H6,HR,IMG,INPUT,INS,LABEL,LEGEND,LI,OL,OPTION,P,PRE,SELECT,SPAN,STRONG,SUB,SUP,TEXTAREA,UL";
			s = s.split(",");
		for(var i=s.length-1,t;t=s[i];i--){
			this.prototype[t] = function(){
				Array.prototype.unshift.call(arguments,arguments.callee.nodeName);
				return this.NODE.apply(this,arguments);
			};
			this.prototype[t].nodeName = t.toLowerCase()
		}
	}
});



/** *************************************************************************************************************
  * Selector
  *********************************************************************************************************** **/
compono.Selector = compono.Class({
	spaces:/^\s+/,
	comma:/\s*,\s*/,
	html:compono.HTMLElements.Element,
	constructor:function(rule,scope,test){
		if(rule){
			return this.query(rule,scope,test).toDOMArray();
		};
		return this
	},
	query:function(rule,scope,test){
		var i, l, prop, selector, $function, buffer=[], finalResult=[], baserule, result;

		if(!rule){
			return [];
		}
		
		//testing the rule comma
		if(this.comma.test(rule)){
			//using the function itself
			for(var i=0,r,z=rule.split(this.comma);i<z.length;i++){
				finalResult = finalResult.concat(arguments.callee.call(this,z[i],scope,test))
			};
			return test ? new Boolean(finalResult.length>0) : finalResult;
		};
		
		baserule = rule;
		scope = [scope||document];
		
		test = test || false;
		
		//labeling the while to force the if clause break the for...in loop
		//testing if the rule has text in it
		START:
		while(rule.length){
			
			//navigating in the syntax to recognize what structure is
			for(prop in this.syntax){
				
				//testing if the prop from syntax match with some info in the prototype
				if(prop in this){
					
					if(this.syntax[prop].test(rule)){
		
						selector = this.syntax[prop].exec(rule);
						
						//cleaning the current selector from the entire selector
						rule = rule.substr(selector[0].length).replace(this.spaces,"");

						//it can be used by the rule itself and/or with some sub-function
						//_this["#"]
						//_this[":"]["first-child"]
						$function = this[ prop ];

						if(typeof($function)=="object"){
							$function = selector[1] in $function ? $function[ selector[1] ] : $function[ prop ]
						};
						
						if($function){
							
							selector[selector.length] = test;
						
							for(i=0,l=scope.length;i<l;i++){
								
								//fixing the first part of the selector with the current scope;
								selector[0] = scope[i];
								
								//running the $function with the selector as args
								//first selector args is the scope;
								result = $function.apply(this,selector);
								
								if(result){
								
									//$function can return any kind of info (boolean, Array, HTMLCollection or Node)
									if(typeof(result)=="boolean" && result==true){

										//restarting the 'result', because it's a boolean and it needs to be a node;
										result = scope[i];
										buffer[buffer.length] = scope[i]

									}else if(result instanceof Array || (result.length && typeof(result)!="string")){
									
										buffer = result.concat(buffer)
										
									}else if(result.nodeType){
										
										buffer[buffer.length] = result
										
									};
									
									//if it's in the last rule it means that we achived our target
									if(rule.length==0){
										finalResult = finalResult.concat(result)
									}
								}
							}
						};
						
						//restarting the scope based on the buffer;
						scope = buffer;
						
						//restarting the buffer
						buffer = [];
					
						//if some syntax match with the rule the for...in loop should be canceled
						continue START
					}
				}
			};
			
			//if the for...in loop didn't change the rule, it means there's no match
			if(baserule === rule){
				finalResult = [];
			}
		};
		
		return test ? new Boolean( finalResult.length > 0 ) : finalResult;
	},
	syntax:{
		"#":/^#([\w-_]+)/,
		"*":/^([*\w-_]+)/,
		".":/^\.([\w-_]+)/,
		":":/^:([\w-_]+)(?:\(([^)]+)?\))?/,
		"%":/^%([\w-_]+)/,
		"+":/^([+~<>])\s+(\w+)/,
		"[]":{
			re:/^(?:\[([\w-_]+)(?:([~$*|=^]{1,2})['"]?([.:/\w-_\s#]+)["']?)?\])/,
			test:function(str){
				return this.re.test(str);
			},
			exec:function(str){
				var x = this.re.exec(str);
				return x ? [x[0],x[2],x[1],x[3]] : null;
			}
		}
	},
	"*":function(scope,tag,test){
		if(test==true){
			return scope.nodeName.toLowerCase() == tag.toLowerCase();
		};
		return Array.toArray(scope.getElementsByTagName(tag))
	},
	"#":function(scope,id,test){	
		return (test==true || scope!==document) ? this["[]"]["="](scope,"=","id",id) : document.getElementById(id);
	},
	"%":function(scope,name,test){	
		return (test==true || scope!==document) ? this["[]"]["="](scope,"=","name",name) : Array.toArray(document.getElementsByName(name));
	},
	".":function(scope,classname){	
		if(scope === document){
			var a = arguments.callee;
			return this["*"](scope,"*").filter(function(o){
						return a.call(this,o,classname)
					},this)
		};
		return this.html.hasClassName.call(scope,classname)
	},
	"+":{
		">":function(scope,op,next){
			var children = this.html.getChildren.call(scope);
			if(next!="*"){
				next = next.toUpperCase();
				children = children.filter(function(t){ return t.nodeName == next },this)
			};
			return children.length ? children : false;
		},
		"<":function(scope,op,next){
			if(next!="*"){
				var o = this.html.parent.call(scope)
				return o.nodeName.toLowerCase()==next.toLowerCase() ? o : false;
			}else{
				return this.html.parent.call(scope);
			};
			return false
		},
		"~":function(scope,op,next,test){
			if(test){
				return next.toLowerCase() == scope.nodeName.toLowerCase()
			};
			if(next){
				var n=[], f=(n=="*"?this.html.next:this.html.nextOfType), o=f.call(scope,next);
				while(o){
					n.push(o);
					o = f.call(o,next);
				};
				return n
			};
			return false
		},
		"-":function(scope,op,previous,test){
			if(test){
				return previous.toLowerCase() == scope.nodeName.toLowerCase()
			};
			if(next){
				var n=[], f=(n=="*"?this.html.previous:this.html.previousOfType), o=f.call(scope,next);
				while(o){
					n.push(o);
					o = f.call(o,next);
				};
				return n
			};
			return false
		},
		"+":function(scope,op,next){
			var n = this.html.next.call(scope);
			return (n.nodeType && (next == "*" || next == n.nodeName.toLowerCase())) ? n : false
		}
	},
	"[]":{
		"[]":function(scope,op,attr,value){		return scope.getAttribute(attr) != null},
		"^=":function(scope,op,attr,value){		return scope.getAttribute(attr).indexOf(value) == 0 },
		"*=":function(scope,op,attr,value){		return scope.getAttribute(attr).indexOf(value) > -1 },
		"~=":function(scope,op,attr,value){		return compono.hash.selector.get(value).test(scope.getAttribute(attr)) },
		"|=":function(scope,op,attr,value){		return compono.hash.selector.get(value).test(scope.getAttribute(attr)) },
		"=":function(scope,op,attr,value){		return scope.getAttribute(attr) == value},
		"$=":function(scope,op,attr,value){		
			var v = scope.getAttribute(attr);
			return v.substring(v.length-value.length,v.length) == value
		}
	},
	":":{
		"target":function(scope,name){			
			return window.location.hash && (window.location.hash.substr(1) == scope.getAttribute("id")) 
		},
		"elements":function(scope,name){		return this("input, textarea, select, button",scope)},
		"checkbox":function(scope,name){		return this["[]"]["="](scope,"=","type",name)},
		"radio":function(scope,name){			return this["[]"]["="](scope,"=","type",name)},
		"file":function(scope,name){			return this["[]"]["="](scope,"=","type",name)},
		"text":function(scope,name){			return this["[]"]["="](scope,"=","type",name)},
		"button":function(scope,name){			return this["[]"]["="](scope,"=","type",name)},
		"image":function(scope,name){			return this["[]"]["="](scope,"=","type",name)},
		"submit":function(scope,name){			return this["[]"]["="](scope,"=","type",name)},
		"hidden":function(scope,name){			return this["[]"]["="](scope,"=","type",name)},
		"password":function(scope,name){		return this["[]"]["="](scope,"=","type",name)},
		"reset":function(scope,name){			return this["[]"]["="](scope,"=","type",name)},
		"root":function(scope,name){			return document.documentElement||document.body.parentNode},
		"selected":function(scope,name){		return scope.selected},
		"checked":function(scope,name){			return scope.checked},
		"unchecked":function(scope,name){		return !scope.checked},
		"enabled":function(scope,name){			return !(scope.disabled)},
		"disabled":function(scope,name){		return scope.disabled},
		"empty":function(scope,name){			return scope.childNodes.length>0&&scope.getElementsByTagName("*").length==0},
		"contains":function(scope,name,value){	return scope.innerHTML.indexOf(value)>-1},
		"lang":function(scope,name,value){		return this["[]"]["|="](scope,"|=","lang",value)},
		"first-child":function(scope,name){		return this.html.first.call(scope.parentNode)===scope},
		"first-of-type":function(scope,name){	return this.html.firstOfType.call(scope.parentNode,scope.nodeName)===scope},
		"last-child":function(scope,name){		return this.html.last.call(scope.parentNode)===scope},
		"last-of-type":function(scope,name){	return this.html.lastOfType.call(scope.parentNode,scope.nodeName)===scope},
		"only-child":function(scope,name){		return this.html.getChildren.call(scope.parentNode).length==1},
		"only-of-type":function(scope,name){
			return this.html.getChildren.call(scope.parentNode).filter(function(o){
						return o.nodeName == this.nodeName
					},scope).length==1
		},
		"nth-child":function(scope,value){},
		"nth-last-child":function(scope,value){},
		"nth-of-type":function(scope,value){},
		"nth-last-of-type":function(scope,value){},
		"not":function(scope,name,value){		return this.query(value,scope,true) == false},
		"has":function(scope,name,value){
			return this.query(value,scope,true);
		}
	},
	"::":function(scope,event){
		//scope.event(event);
		return scope;
	}
});





/** *************************************************************************************************************
  * Hash
  *********************************************************************************************************** **/
compono.Hash = compono.Class({
	name:"Hash",
	constructor:function(p){
		if(typeof(p)=="object"){
			Object.extend(p,this);
		}
	},
	parseQueryString:function(q){
		var r=/([^=]+)=(.+?)(?:&|$)/ig, s="";
		while(s=r.exec(q)){
			this[s[1]] = s[2]||""
		};
		return this;
	},
	parseJSON:function(q){
		var r=/([^:]+):(.+?)(?:,|$)/ig, s="";
		while(s=r.exec(q)){
			this[s[1]] = s[2]||""
		};
		return this;
	},
	toJSON:function(){
		return "{"+this.join()+"}";
	},
	toString:function(){
		return this.join();
	},
	toQueryString:function(){
		return this.join("&","=");
	},
	keys:function(h){
		var k=[], s="";
		for(s in this){
			if(!(s in this.constructor.prototype)){
				k[k.length] = s
			}
		};
		return k;
	},
	values:function(h){
		var v=[], s="";
		for(s in this){
			if(!(s in this.constructor.prototype)){
				v[v.length] = this[s]
			}
		};
		return v;
	},
	append:function(a,v){
		if(typeof(a) == "object"){
			Object.extend(a,this)
		}else{
			if(!(a in this.constructor.prototype)){
				this[a]=v
			}
		};
		return true;
	},
	remove:function(a){
		if(!(a in this.constructor.prototype)){
			delete this[a]
		};
		return true;
	},
	indexOf:function(str, si){
		if(!str){return -1;}
		var keys=this.keys(), si=si||0;
		for(var i=si,s;s=this[(keys[i])];i++){
			if(str === s)return i;
		};
		return -1;
	},
	lastIndexOf:function(str, si){
		if(!str){return -1;}
		var keys=this.keys(), si=si||keys.length-1;
		for(var i=si,s;s=this[(keys[i])];i--){
			if(str === s)return i;
		};
		return -1;
	},
	forEach:function(h, s){
		if(typeof(h)!="function"){ return false; };
		var p,i=0,s=s||this;
		for(p in this){
			if(!(p in this.constructor.prototype)){
				h.call(s,p,this[p],i,this);
				i++;
			}
		};
		return this;
	},
	filter:function(h, s){
		if(typeof(h)!="function"){ return false; };
		var r=new this.constructor(),s,i=0,s=s||this;
		for(p in this){
			if(!(p in this.constructor.prototype)){
				if(h.call(s,p,this[p],i,this)){
					r[p]=this[p];
					i++;
				}
			}
		};
		return r;
	},
	every:function(h, s){
		if(typeof(h)!="function"){ return false; };
		var p,i=0,s=s||this;
		for(p in this){
			if(!(p in this.constructor.prototype)){
				if(!h.call(s,p,this[p],i,this)){return false};
				i++;
			}
		};
		return true;
	},
	some:function(h, s){
		if (typeof(h)!="function"){return false;}
		var p,i=0,s=s||this;
		for(p in this){
			if(!(p in this.constructor.prototype)){
				if(h.call(s,p,this[p],i,this)){return true};
				i++;
			}
		};
		return false;
	},
	map:function(h, s){
		if(typeof(h)!="function"){ return false; };
		var p,r=new this.constructor(),i=0,s=s||this;
		for(p in this){
			if(!(p in this.constructor.prototype)){
				r[p] = h.call(s,p,this[p],i,this);
				i++;
			}
		};
		return r;
	},
	join:function(sep,sep1){
		var a,s="",amp="",sep=sep||",",eq=sep1||":",v="";
		for(a in this){
			if(!(a in this.constructor.prototype)){
				if(this[a].constructor==Array){
					v = a + eq + encodeURIComponent(this[a].join(","));
				}else{
					v = a + eq + encodeURIComponent(this[a]||"");
				}
				s += amp + v;
				amp=sep;
			}
		};
		return s;
	}
});

	
/** *************************************************************************************************************
  * Wiki
  *********************************************************************************************************** **/
compono.Wiki = compono.Static({
	sintax:[
		{get:/\{\{([^\|]+)(?:\|([^\}]*))?\}\}/, template:function(){
			return "<label for=\""+ (RegExp.lastParen?RegExp.lastParen:RegExp.$1) + "\">" + RegExp.$1 + "</label>"}
		},
		{get:/\[\[([^\|]+)(?:\|([^\]]*))?\]\]/, template:function(){
			return "<a href=\""+ (RegExp.lastParen?RegExp.lastParen:RegExp.$1) + "\">" + RegExp.$1 + "</a>"}
		},
		{get:/!!(.+?)!!/gm, template:"<span class=\"h\">$1</span>"},
		{get:/(?:\/\/(.+?)\/\/)/gm, template:"<span class=\"s\">$1</span>"},
		{get:/--(.+?)--/gm, template:"<s>$1</s>"},
		{get:/''(.+?)''/gm, template:"<em>$1</em>"},
		{get:/\*\*(.+?)\*\*/gm, template:"<strong>$1</strong>"},
		{get:/__(.+?)__/gm, template:"<u>$1</u>"},
		{get:/\n/gm, template:"<br/>"}
	],
	render:function(c){
		if(c){
			for(var i=0,o,l=this.sintax.length;i<l;i++){
				o = this.sintax[i];
				c = c.replace(o.get,o.template);
			};
			return c;
		};
		return false;
	}
});


String.prototype.trim=function(){
	return this.replace(/^\s*(.*?)\s*$/,"$1");
};
String.prototype.toQueryString = function(o){
	var v="",x="";
	for(var i in o){
		v += x + i + "=" + o[i]; x="&"
	};
	return v
};
String.prototype.toJSON = function(scope){
	var str = this;
	if(this.length){
		if(/(?:^\{)|(?:\}$)/.test(str) == false){
			str = "{" + str + "}";
		};
		str = str.replace(/\n/,"");
		return (function(){ return eval("(" + str + ")"); } ).call(scope||window);
	};
	return {JSON_EMPTY:true};
};


Array.prototype.format = function(template){
	if(template){
		function f(s,p){
			return arguments.callee.args[p];
		};
		f.args = this;
		return template.replace(/\{(?:([\w_-]+)(?:\:([\w_-]+))?)\}/gim, f)
	}
};

String.prototype.format = function(args){
	var a= arguments.length > 1 ? arguments : args;
	return this.replace(/\{(?:([\w_-]+)(?:\:([\w_-]+))?)\}/gim, function(str,p1,p2,ix,as){
		var x = a[p1];
		switch(p2){
			case "Q":
				var v="",s="",i="";
				for(var i in x){
					v+=s+i+"="+x[i];
					s="&"
				};
				x=v;
				break;
		};
		return x||""
	});
};

Date.prototype.getMonthDays = function(){
	return 32 - new Date(this.getFullYear(), this.getMonth(), 32).getDate()
};


Object.getByPath = function(path, scope){
	var current, parent, base=[];
	path = path.split(".");
	current = scope || window;
	for(var i=0; current=current[ path[i] ]; i++){
		base[base.length]=current;
		if(i==path.length-1){	break;	}
		parent = current;
	};
	base.current = current;
	base.parent = parent;
	return base;
};


Function.prototype.map = function(a,s){
	if(a){
		for(var i=0,r=[],s=s||window,l=a.length;i<l;i++){
			r.push(this.call(s,a[i]))
		};
		return r;
	};
	return null
};

Function.prototype.test = function(scope, _catch, args){
	scope = scope || window;
	try{
			return this.apply(scope, args);
	}catch(error){
		if(_catch&&typeof(_catch)=="function"){
			if(args){
				args.push(error)
			}else{
				args = [error];
			};
			return _catch.apply(scope, args);
		};
		return error
	}
};

Array.prototype.test=function(test,scope){
	for(var i=0,s=s||this;i<this.length;i++){
		try{ 
			return test.call(scope,this[i],i); 
		}catch(e){
		}
	};
	return false
};

Array.prototype.revertTest=function(test,scope){
	for(var i=this.length-1,s=s||this;i>-1;i--){
		try{ 
			return test.call(scope,this[i],i); 
		}catch(e){
		}
	};
	return false
};


Function.prototype.interval = function(time,scope,args,event){
	if(this.TIMER_TYPE&&this.TIMER_TYPE=='timeout'){
		this.timeout(false);
	};
	if(this.TIMER_ID){
		window.clearInterval(this.TIMER_ID);
		this.TIMER_ID = -1;
		this.HAS_TIMER = false;
		this.TIMER_COUNT = 0;
		this.TIMER_RUN = false;
		this.TIMER_TYPE = false;
		if(time==false)return false;
	};
	var u = function(){
		var a = arguments.callee; 
		a.run.TIMER_COUNT++;
		if(a.event.call(a.scope,a.run,a.args)==false){
			return false
		};
		if(a.run.apply(a.scope,a.args)==false){
			arguments.callee.call(a.run,false)
		}
	};
	u.scope = scope||window;
	u.event = event||function(){return true;}
	u.args = args||[];
	u.run = this;
	
	this.HAS_TIMER = true;
	this.TIMER_COUNT = 0;
	this.TIMER_RUN = u;
	this.TIMER_TYPE = "interval";
	
	return this.TIMER_ID = window.setInterval(u, (time||1)*1000);
};


Function.prototype.timeout = function(time,scope,args,event){
	if(this.TIMER_TYPE&&this.TIMER_TYPE=='interval'){
		this.interval(false);
	};
	if(this.TIMER_ID){
		window.clearInterval(this.TIMER_ID)
		this.TIMER_ID = -1;
		this.HAS_TIMER = false;
		this.TIMER_COUNT = 0;
		this.TIMER_RUN = false;
		this.TIMER_TYPE = false;
		if(time==false)return false;
	};
	var u = function(){
		var a = arguments.callee; 
		if(a.event.call(a.scope,a.run,a.args)==false){
			return false
		};
		a.run.apply(a.scope,a.args);
		a.run.TIMER_ID = false;
		a.run.HAS_TIMER = false;
	};
	u.scope = scope||window;
	u.run = this;
	u.event = event || function(){return true;};
	u.args = args||[];
	
	this.HAS_TIMER = true;
	this.TIMER_COUNT = 0;
	this.TIMER_RUN = u;
	this.TIMER_TYPE = "timeout";
	
	return this.TIMER_ID = window.setTimeout(u, (time||1)*1000);
};


if(!Array.prototype.indexOf){
	Array.indexOf = Array.prototype.indexOf = function(s, si){
		for(var i=si||0,z=this.length;i<z;i++){
			if(i in this && s === this[i]){ 
				return i; 
			};
		};
		return -1;
	};
};

if(!Array.prototype.lastIndexOf){
	Array.lastIndexOf = Array.prototype.lastIndexOf = function(s, si){
		for(var i=si||this.length;i>0; i--){
			if(i in this && s === this[i]){
				return i;
			}
		};
		return -1;
	};
};

if(!Array.prototype.forEach)
{
	Array.forEach = Array.prototype.forEach = function(handler, scope)
	{
		if(typeof(handler) != "function")
		{
			return false;
		};
		scope = scope || window;
		for(var i=0,z=this.length;i<z;i++)
		{
			if(i in this)
			{
				handler.call(scope, this[i], i, this)
			}
		};
	};
};

if(!Array.prototype.filter){
	Array.filter = Array.prototype.filter = function(handler, scope)
	{
		if(typeof(handler) != "function")
		{
			return false;
		};
		var result=[], scope = scope || window;
		for(var i=0,z=this.length;i<z;i++)
		{
			if(i in this && handler.call(scope, this[i], i, this))
			{
				result.push(this[i]);
			}
		};
		return result;
	};
};

if(!Array.prototype.every)
{
	Array.every = Array.prototype.every = function(handler, scope)
	{
		if(typeof(handler) != "function")
		{
			return false;
		};
		scope = scope || window;
		for(var i=0,z=this.length;i<z;i++)
		{
			if(i in this && !handler.call(scope, this[i], i, this))
			{
				return false;
			}
		};
		return true;
	};
};

if(!Array.prototype.map)
{
	Array.map = Array.prototype.map = function(h, o)
	{
		if(typeof(handler) != "function")
		{
			return false;
		};
		var result=[], scope = scope || window;
		for(var i=0,z=this.length; i<z; i++)
		{
			if(i in this)
			{
				result.push(	handler.call(scope, this[i], i, this) || this[i]	);
			}
		};
		return result;
	};
};

if(!Array.prototype.some)
{
	Array.some = Array.prototype.some = function(handler, scope)
	{
		if(typeof(handler) != "function")
		{
			return false;
		};
		scope = scope || window;
		for(var i=0,z=this.length;i<z;i++)
		{
			if(i in this && handler.call(scope, this[i], i, this) )
			{
				return true;
			}
		};
		return false;
	}
};

Array.prototype.currentIndex = -1; 

Array.prototype.first = function()
{ 
	if(this.hasOwnProperty(0))
	{
		this.currentIndex = 1;
		return this[0];
	};
	return null
};

Array.prototype.last = function()
{ 
	var i = this.length-1;
	if(this.hasOwnProperty(i))
	{
		this.currentIndex = i;
		return this[i];
	};
	return null
};

Array.prototype.next = function()
{
	if(this.currentIndex == -1){
		this.currentIndex = 0;
	}
	if(this.hasOwnProperty(this.currentIndex))
	{
		var n = this[this.currentIndex];
		this.currentIndex = this.currentIndex < this.length ? this.currentIndex+1 : this.length;
		return n
	};
	return null;
};

Array.prototype.previous = function()
{
	if(this.currentIndex >= this.length )
	{ 
		this.currentIndex = this.length - 1;
	};
	if(this.hasOwnProperty(this.currentIndex))
	{
		var item = this[this.currentIndex];
		this.currentIndex = this.currentIndex >= 0 ? this.currentIndex-1 : -1;
		return item
	};
	return null;
};

Array.toDOMArray = Array.prototype.toDOMArray = function(collection)
{
	return new compono.DOMArray(collection || this);
};

Array.toArray = Array.prototype.toArray = function(collection)
{
	if(!collection){
		return false
	}
	else if(collection instanceof Array)
	{	
		return collection
	}
	else
	{
		try{
			return Array.prototype.slice.call(collection,0);
		}
		catch(e)
		{
			for(var i=collection.length-1,result=[]; i>=0; i--)
			{
				result[i] = collection[i];
			};
			return result;
		}
	}
};


/** *****************************************************************************************************************
 *	EXECUTION
 */
if(compono.extend!=false&&(document.documentElement&&document.documentElement.getAttribute("compono_extend")!="false"))
{
	Object.extend(compono.prototype, window);
};

if(Object.hasOwnProperty.call(window,"HTMLElement"))
{
	if(HTMLElement.prototype)
	{
		Object.extend(compono.HTMLElements.Element, HTMLElement.prototype);
	}
};

Object.extendForBatchProcessing(
	compono.HTMLElements.Element, 
	compono.DOMArray.prototype,
	false,
	function(handler, args){
		var result = new compono.DOMArray();
		if(this.length <= 0){
			return this;
		};
		for(var i=0, length = this.length; i < length; i++){
			result.push( handler.apply( compono.$( this[i] ), args ) )
		};
		return result;
	
	}
);